﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace 页面置换算法项目
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }
        // 页面类，用于存储页面的相关信息
        class Page
        {
            public int PageNumber { get; set; }//页面号
            public int LastUsedTime { get; set; }//最近使用时间
            public int UseCount { get; set; }//使用次数
        }
        // 页面置换算法的基类
        abstract class PageReplacementAlgorithmBase
        {
            public List<Page> memoryPages = new List<Page>(3);//Page对象列表，用于存储当前驻留在内存中的页面信息,驻留集
            protected int pageSize = 7;//页面大小
            protected int memoryPageCount = 3;//驻留集大小
            protected int nullMemoryPageCount = 3;//空驻留集数量
            protected int memoryVisitTime = 100;//访问内存的时间
            protected int pageFaultTime = 800;//缺页的时间
            protected int tlbTime = 10;//访问快表的时间
            protected bool useTlb = false;//是否使用快表
            protected Dictionary<int, int> tlb;//字典，用于模拟快表，key-逻辑页号，value-物理块号
            protected List<int> pageFaults;//整数列表，用于记录每次页面访问时是否发生了缺页中断
            protected List<int> visitTimes;//整数列表，用于记录每次页面访问所花费的时间
                                           //构造函数
            public PageReplacementAlgorithmBase(int pageSize, int memoryPageCount, int nullMemoryPageCount, int memoryVisitTime, int pageFaultTime, int tlbTime, bool useTlb)
            {
                this.pageSize = pageSize;
                this.memoryPageCount = memoryPageCount;
                this.nullMemoryPageCount = nullMemoryPageCount;
                this.memoryVisitTime = memoryVisitTime;
                this.pageFaultTime = pageFaultTime;
                this.tlbTime = tlbTime;
                this.useTlb = useTlb;
                memoryPages = new List<Page>(); //驻留集
                tlb = new Dictionary<int, int>();//快表信息
                pageFaults = new List<int>();//缺页信息
                visitTimes = new List<int>();//访问页面时间
            }

            //抽象方法，用于处理页面访问
            public abstract void VisitPage(int pageNumber);

            // 计算逻辑地址对应的逻辑页号(逻辑地址：logicalAddress)
            protected int GetLogicalPageNumber(int logicalAddress)
            {
                return logicalAddress / pageSize;
            }

            //抽象方法,用于处理缺页中断
            public abstract void HandlePageFault(int pageNumber);

            //抽象方法，用于置换页面
            public abstract void ReplacePage(int pageNumber);

            //用于计算访问内存的时间
            protected int VisitMemory(int pageNumber)
            {
                int visitTime = 0;
                if (useTlb == true)
                {
                    if (tlb.ContainsKey(pageNumber) == true)
                    {
                        visitTime = visitTime + tlbTime;
                    }
                    else
                    {
                        visitTime = visitTime + tlbTime + memoryVisitTime;
                    }
                }
                else
                {
                    visitTime = visitTime + memoryVisitTime;
                }
                visitTimes.Add(visitTime);
                return visitTime;
            }
        }


        // FIFO算法
        class FIFOPageReplacement : PageReplacementAlgorithmBase
        {
            protected int nextPage = 0;
            //构造函数
            public FIFOPageReplacement(int pageSize, int memoryPageCount,int nullMemoryPageCount, int memoryVisitTime,  int pageFaultTime, int tlbTime, bool useTlb) : base(pageSize, memoryPageCount, nullMemoryPageCount, memoryVisitTime, pageFaultTime, tlbTime, useTlb)
            {

            }

            //判断函数，用于判断页面是否在内存中
            protected bool ContainPage(int pageNumber)
            {
                for (int i = 0; i < memoryPages.Count; i++)
                {
                    if (memoryPages[i].PageNumber == pageNumber)
                    {
                        return true;
                    }
                }
                return false;
            }

            //置换算法
            public override void ReplacePage(int pageNumber)
            {
                memoryPages[nextPage] = new Page { PageNumber = pageNumber, LastUsedTime = Environment.TickCount, UseCount = 0 };
                nextPage = (nextPage + 1) % memoryPageCount;
            }

            //缺页处理函数
            public override void HandlePageFault(int pageNumber)
            {                
                if (nullMemoryPageCount != 0 && memoryPages.Count==0)
                {
                    // 直接添加新页面
                    Page newPage= new Page();
                    newPage.PageNumber = pageNumber;
                    newPage.LastUsedTime = Environment.TickCount;
                    newPage.UseCount = 0;
                    memoryPages.Add(newPage);
                    for (int i = 0; i < memoryPageCount - 1; i++){
                        Page newPage1 = new Page();
                        newPage1.PageNumber = -1;
                        newPage1.LastUsedTime = Environment.TickCount;
                        newPage1.UseCount = 0;
                        memoryPages.Add(newPage1);
                    }
                    nullMemoryPageCount--;
                }
                else
                {
                    if(nullMemoryPageCount != 0)
                    {
                        memoryPages[memoryPageCount-nullMemoryPageCount].PageNumber=pageNumber;
                        nullMemoryPageCount--;
                    }
                    // 执行页面置换算法
                    else
                    {
                        ReplacePage(pageNumber);
                    }
                    
                }
                pageFaults.Add(1);
            }

            //访存函数
            public override void VisitPage(int pageNumber)
            {
                //缺页了
                if (ContainPage(pageNumber) == false)
                {
                    HandlePageFault(pageNumber);
                }
                //没有缺页
                VisitMemory(pageNumber);
            }
        }

        private void fifoButton_Click(object sender, EventArgs e)
        {
            string[] page = textBox1.Text.Split(',');//页号存入数组
            int[] pages = Array.ConvertAll(page, int.Parse);
            FIFOPageReplacement fifo = new FIFOPageReplacement(7, 3, 3, 100, 800, 10, false);

            // 创建一个新的线程来执行页面置换算法
            Thread thread = new Thread(() =>
            {
                string[] fifoText = new string[int.Parse(memoryPageCountTextBox.Text)];
                for (int i = 0; i < pages.Length; i++)
                {
                    fifo.VisitPage(pages[i]);
                    // 使用 Invoke 方法更新界面
                    UpdateTextBoxes(fifo,fifoText);
                    Thread.Sleep(1000); // 延迟 1 秒，模拟页面置换过程
                }
            });
            thread.Start();
        }

        private void UpdateTextBoxes(FIFOPageReplacement fifo, string[] fifoText)
        {

            // 检查是否需要调用 UI 线程
            if (InvokeRequired)
            {
                // 使用 Invoke 将更新操作委托给 UI 线程
                Invoke(new Action(() => UpdateTextBoxes(fifo, fifoText)));
                return;
            }

            for (int i = 0; i < fifoText.Length; i++)
            {
                if (fifo.memoryPages[i].PageNumber == -1)
                {
                    fifoText[i] += " " + " ";
                }
                else
                {
                    fifoText[i] += fifo.memoryPages[i].PageNumber + " ";
                }    
            }
            setText(fifoText);
        }

        private void setText(string[] fifoText)
        {
            string text = "";
            for (int i = 0; i < fifoText.Length; i++)
            {
                text += fifoText[i] + "\r\n";
            }
            this.fifoTextBox.Text = text;
        }

        private void textBox6_TextChanged(object sender, EventArgs e)
        {

        }

        private void textBox5_TextChanged(object sender, EventArgs e)
        {

        }


    }
}
